package cmpe451.group7.ourcity.entity;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;

/**
 * Entity class for places.
 */
@Entity
@Table(name = "place", uniqueConstraints = @UniqueConstraint(columnNames = {
		"country", "city", "placeName" }))
public class Place implements Serializable {

	public static final String BOGAZICI_POSITION = "41.086021, 29.044010";
	private static final long serialVersionUID = 1L;

	private long placeID;
	private long placeCreatorID;

	private String placeName;
	private String country;
	private String city;
	private int likeCount;
	private double latitude;
	private double longitude;
	private Date creationDate;
	private Set<Tag> tags = new HashSet<Tag>();
	private Set<Multimedia> multimedia = new HashSet<Multimedia>();

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "placeID")
	public long getPlaceID() {
		return placeID;
	}

	public void setPlaceID(long placeID) {
		this.placeID = placeID;
	}

	@Column(name = "placeName", nullable = false)
	public String getPlaceName() {
		return placeName;
	}

	public void setPlaceName(String placeName) {
		this.placeName = placeName;
	}

	@Column(name = "city", nullable = false)
	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	@Column(name = "country", nullable = false)
	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		this.country = country;
	}

	@Column(name = "likeCount")
	public int getLikeCount() {
		return likeCount;
	}

	public void setLikeCount(int likeCount) {
		this.likeCount = likeCount;
	}

	@Column(name = "latitude")
	public double getLatitude() {
		return latitude;
	}

	public void setLatitude(double latitude) {
		this.latitude = latitude;
	}

	@Column(name = "longitude")
	public double getLongitude() {
		return longitude;
	}

	public void setLongitude(double longitude) {
		this.longitude = longitude;
	}

	@Column(name = "creationDate")
	public Date getCreationDate() {
		return creationDate;
	}

	public void setCreationDate(Date creationDate) {
		if (creationDate != null)
			this.creationDate = new Date(creationDate.getTime());
		else
			this.creationDate = null;
	}

	@ManyToMany(fetch = FetchType.LAZY)
	// cascade = { CascadeType.PERSIST, CascadeType.MERGE,
	// CascadeType.REFRESH },
	// @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
	@JoinTable(name = "place_tag", joinColumns = { @JoinColumn(name = "placeID") }, inverseJoinColumns = { @JoinColumn(name = "tagID") })
	public Set<Tag> getTags() {
		return tags;
	}

	public void setTags(Set<Tag> tags) {
		this.tags = tags;
	}

	public void addTag(Tag t) {
		tags.add(t);
	}

	/**
	 * Returns the name of the tags in a CSV fashion
	 * 
	 * @return
	 */
	@Transient
	public String getCSVTags() {
		String res = "";

		if (tags == null)
			return "";

		for (Iterator<Tag> iterator = tags.iterator(); iterator.hasNext();) {
			Tag t = (Tag) iterator.next();
			res += t.getTagName() + ", ";
		}

		return res.substring(0, Math.max(0, res.length() - 2));
	}

	@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
	@JoinColumn(name = "PLACE_ID")
	public Set<Multimedia> getMultimedia() {
		return multimedia;
	}

	public void setMultimedia(Set<Multimedia> multimedia) {
		this.multimedia = multimedia;
	}

	public void addMultimedia(Multimedia item) {
		multimedia.add(item);
	}

	@Transient
	public String getCenterInfo() {
		if (latitude == 0 && longitude == 0)
			return BOGAZICI_POSITION;

		return latitude + ", " + longitude;
	}

	/* AUTO-GENERATED EQUALS & HASH FUNCTIONS */

	@Transient
	public String getDay() {
		if (creationDate != null)
			return new SimpleDateFormat("EEE, dd/MM/yyyy").format(creationDate);
		else
			return "";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((city == null) ? 0 : city.hashCode());
		result = prime * result + ((country == null) ? 0 : country.hashCode());
		result = prime * result + (int) (placeID ^ (placeID >>> 32));
		result = prime * result
				+ ((placeName == null) ? 0 : placeName.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Place other = (Place) obj;
		if (city == null) {
			if (other.city != null)
				return false;
		} else if (!city.equals(other.city))
			return false;
		if (country == null) {
			if (other.country != null)
				return false;
		} else if (!country.equals(other.country))
			return false;
		if (placeID != other.placeID)
			return false;
		if (placeName == null) {
			if (other.placeName != null)
				return false;
		} else if (!placeName.equals(other.placeName))
			return false;
		return true;
	}

	public long getPlaceCreatorID() {
		return placeCreatorID;
	}

	public void setPlaceCreatorID(long placeCreatorID) {
		this.placeCreatorID = placeCreatorID;
	}

}
